home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <sys/socket.h>
- #include <netdb.h>
- #include "netconf.h"
- #include "../userconf/userconf.h"
- #include "internal.h"
- #include "../misc/misc.h"
- #include "../paths.h"
- #include "netconf.m"
-
- static NETCONF_HELP_FILE help_aliases ("ip_aliases");
- static CONFIG_FILE f_aliases (PROC_NET_ALIASES
- ,help_aliases
- ,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
- static CONFIG_FILE f_alias_types (PROC_NET_ALIAS_TYPES
- ,help_aliases
- ,CONFIGF_OPTIONNAL|CONFIGF_PROBED);
-
-
- /* #Specification: netconf / aliases / strategy
- linuxconf will automaticly manage/assign/remove all ip_alias based
- on the definitions it received. It will select by itself the
- alias number (ethx:NUMBER) by monitoring the currently allocated
- ones.
- */
-
- PUBLIC IP_ALIAS::IP_ALIAS(int _num, const char *_ip)
- {
- num = _num;
- ip.setfrom (_ip);
- }
-
- PUBLIC IP_ALIAS::IP_ALIAS(const char *_ip)
- {
- num = -1; // Not yet setup in the kernel
- ip.setfrom (_ip);
- }
-
-
- PUBLIC int IP_ALIAS::unset (const char *devname)
- {
- char cmd[100];
- sprintf (cmd,"%s:%d- 0.0.0.0",devname,num);
- return netconf_system_if ("ifconfig",cmd);
- }
-
- PUBLIC int IP_ALIAS::set (int _num, const char *devname)
- {
- char cmd[100];
- sprintf (cmd,"%s:%d %s",devname,_num,ip.get());
- int ret = netconf_system_if ("ifconfig",cmd);
- if (ret == 0){
- sprintf (cmd,"add %s %s:%d",ip.get(),devname,_num);
- ret = netconf_system_if ("route",cmd);
- }
- return ret;
- }
-
-
- PUBLIC IP_ALIAS *IP_ALIASES::getitem(int no)
- {
- return (IP_ALIAS*)ARRAY::getitem(no);
- }
-
- /*
- Locate one alias from its IP number
- */
- PUBLIC IP_ALIAS *IP_ALIASES::getitem(const char *ip)
- {
- IP_ALIAS *ret = NULL;
- int n = getnb();
- for (int i=0; i<n; i++){
- IP_ALIAS *a = getitem(i);
- if (a->ip.cmp(ip)==0){
- ret = a;
- break;
- }
- }
- return ret;
- }
-
- /*
- Read the aliases currently configured for a device (eth0 for example)
- */
- PUBLIC void IP_ALIASES::readproc (const char *devname)
- {
- FILE *fin = f_aliases.fopen ("r");
- if (fin != NULL){
- char buf[300];
- int len = strlen(devname);
- while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- if (strncmp(buf,devname,len)==0
- && buf[len] == ':'){
- int id;
- int family;
- char ip[100];
- sscanf (buf+len+1,"%d %d %s",&id,&family,ip);
- /* #Specification: netconf / aliases / 0.0.0.0
- The file /proc/net/aliases contains entries
- with an IP number of 0.0.0.0. Theses entries
- are "downed" interface. I suspect they should be
- left out of the table. Anyway, they are ignored
- by linuxconf.
- */
- if (strcmp(ip,"0.0.0.0")!=0){
- add (new IP_ALIAS(id,ip));
- }
- }
- }
- fclose (fin);
- }
- }
-
- /*
- Return the number of the last allocated alias numer (ethx:N)
- */
- PUBLIC int IP_ALIASES::getmaxnum()
- {
- int ret = 0;
- int n = getnb();
- for (int i=0; i<n; i++){
- IP_ALIAS *a = getitem(i);
- if (a->num > ret) ret = a->num;
- }
- return ret;
- }
-
- /*
- Translate a IP number into up to four numbers.
- Return the number of numbers written into tbi.
- */
- static int ipalias_evalip (const char *str, int tbi[4])
- {
- int nb = 0;
- while (*str != '\0'){
- tbi[nb++] = atoi(str);
- str = str_skipdig (str);
- if (*str == '.') str++;
- }
- return nb;
- }
-
- /*
- Record the aliases definition.
- The function setup has to be called after setting all the definition
- */
- PUBLIC int IP_ALIASES::setnew (
- const char *devip, // Ip number of the device
- const char *ips, // A bunch of IP alias to allocate
- char *err) // Collect error messages
- {
- /* #Specification: netconf / aliases / defining many
- The user interface of linuxconf allows you to define several
- IP aliases for a device. These aliases are generally used for
- virtual host httpd server. Many installation will required a fair
- amount of IP number, one for each domain they serve. To help setup
- those aliases, linuxconf do support different syntax.
-
- #
- -You can define menu IP number on a single line.
- -You can define a range of IP number like this x.y.z.a-b. This
- will effectivly define one alias per number from a to b.
- -You can define an alias just by specifying the suffix of the
- ip number. For example, an ethernet device (eth0) may have the IP
- 192.168.1.1. By defining the alias 2 3 4 5, you are effectivly
- defining:
-
- eth0:1 192.168.1.2
- eth0:2 192.168.1.3
- eth0:3 192.168.1.4
- eth0:4 192.168.1.5
- -The abreviated syntax define in the previous paragraph also work
- with ranges. The previous example could be written 2-5.
- -You can use names (fqdn) to setup aliases.
- #
- */
-
- int ret = 0;
- while (1){
- ips = str_skip(ips);
- if (*ips == '\0') break;
- char word[200];
- ips = str_copyword (word,ips);
- if (isdigit (word[0])){
- char *pt = strchr(word,'-');
- int start=0,end=0;
- if (pt != NULL){
- *pt++ = '\0';
- end = atoi(pt);
- }
- char *first = strrchr(word,'.');
- if (first != NULL){
- *first++ = '\0';
- start = atoi(first);
- }else{
- start = atoi(word);
- word[0] = '\0';
- }
- if (end < start) end = start;
- int tbdev[4];
- ipalias_evalip(devip,tbdev);
- int tbspec[4];
- int nbspec = ipalias_evalip(word,tbspec);
- memcpy (tbdev+(3-nbspec),tbspec,nbspec*sizeof(int));
- for (int i=start; i<=end; i++){
- sprintf (word,"%d.%d.%d.%d",tbdev[0],tbdev[1],tbdev[2],i);
- add (new IP_ALIAS (word));
- }
- }else{
- struct hostent *ent = gethostbyname(word);
- if (ent != NULL){
- devices_ip2a (ent,word);
- add (new IP_ALIAS(word));
- }else{
- strcat (err,MSG_U(E_UNKHOST,"Unknown host name "));
- strcat (err,word);
- strcat (err,"\n");
- ret = -1;
- }
- }
- }
- return ret;
- }
-
- static int ipalias_available()
- {
- int ret = 0;
- FILE *fin = f_alias_types.fopen("r");
- if (fin == NULL){
- xconf_error (MSG_U(E_NOALIAS,"No kernel support for devices aliasing"));
- }else{
- char buf[300];
- if (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
- int id = atoi(buf);
- if (id == AF_INET){
- ret = 1;
- break;
- }
- }
- }
- fclose (fin);
- if (!ret){
- ret = netconf_system_if ("modprobe","ip_alias") == 0;
- }
- }
- return ret;
- }
-
- /*
- Install the proper aliases in the kernel.
- Cleanup the one which are not needed anymore.
-
- Return -1 if any errors.
- */
- PUBLIC int IP_ALIASES::setup (const char *devname)
- {
- IP_ALIASES proc;
- proc.readproc(devname);
- int maxnum = proc.getmaxnum();
- int n = getnb();
- int len = maxnum+n+1;
- char lookup[len];
- memset (lookup,0,sizeof(char)*len);
- IP_ALIASES toadd; // Will contain the items that must be added
- toadd.neverdelete();
- int i;
- for (i=0; i<n; i++){
- IP_ALIAS *a = getitem(i);
- IP_ALIAS *ap = proc.getitem(a->ip.get());
- if (ap != NULL){
- // Alias is already installed
- lookup[ap->num] = 1;
- }else{
- toadd.add(a);
- }
- }
- int ret = 0;
- n = proc.getnb();
- for (i=0; i<n; i++){
- IP_ALIAS *a = proc.getitem(i);
- IP_ALIAS *ap = getitem(a->ip.get());
- if (ap == NULL){
- // Alias is already installed and must be removed
- ret |= a->unset (devname);
- }
- }
- n = toadd.getnb();
- if (n > 0){
- if (ipalias_available()){
- int allocnum = 0;
- for (i=0; i<n; i++){
- IP_ALIAS *a = toadd.getitem(i);
- while (lookup[allocnum] != 0) allocnum++;
- ret |= a->set (allocnum,devname);
- allocnum++;
- }
- }else{
- ret = -1;
- }
- }
- return ret;
- }
-
- static char IPALIAS[]="ipalias";
-
- int alias_setup(const char *devname)
- {
- int ret = -1;
- IFCONFIG_INFO info;
- if (ifconfig_getinfo(devname,info)!=-1){
- IP_ALIASES alias;
- SSTRINGS strs;
- linuxconf_getall (IPALIAS,devname,strs,0);
- ret = 0;
- char err[10000];
- err[0] = '\0';
- for (int i=0; i<strs.getnb(); i++){
- SSTRING *s = strs.getitem(i);
- ret |= alias.setnew (info.ip_addr,s->get(),err);
- }
- if (ret == 0){
- ret = alias.setup(devname);
- }else if (err[0] != '\0'){
- xconf_error (MSG_U(E_SETALIAS
- ,"Invalid alias setup for device %s\n%s")
- ,devname,err);
- }
- }
- return ret;
- }
-
- /*
- Install the aliases for all devices
- */
- int alias_setup ()
- {
- int ret = -1;
- SSTRINGS list;
- if (devlist_read (list) != -1){
- int n = list.getnb();
- ret = 0;
- for (int i=0; i<n; i++){
- SSTRING *s = list.getitem(i);
- ret |= alias_setup (s->get());
- }
- }
- return ret;
- }
-
- static void alias_edit(const char *devname)
- {
- SSTRINGS lst;
- linuxconf_getall (IPALIAS,devname,lst,1);
- int i;
- for (i=0; i<10; i++) lst.add(new SSTRING);
- int nof = 0;
- while (1){
- DIALOG dia;
- for (i=0; i<lst.getnb(); i++){
- dia.newf_str (i==0 ? MSG_U(F_IPALIASES,"IP aliases") : ""
- ,*lst.getitem(i));
- }
- char buf[100];
- sprintf (buf,MSG_U(T_IPALIASFORDEV,"IP aliases for device %s")
- ,devname);
- MENU_STATUS code = dia.edit (buf
- ,MSG_U(I_IPALIASFORDEV
- ,"You can enter alternative IP numbers for a\n"
- "network interface. You can enter several numbers\n"
- "per lines. Many time savers syntax are supported\n"
- "Here are some examples for:\n"
- " 192.168.1.10 192.168.1.11 192.168.1.12\n"
- " 192.168.1.10-12\n"
- " 10-12")
- ,help_aliases
- ,nof);
- if (code == MENU_CANCEL || code == MENU_ESCAPE){
- break;
- }else if (code == MENU_ACCEPT){
- if (perm_rootaccess(MSG_U(P_UPDALIAS,"to update IP aliases"))){
- for (i=0; i<lst.getnb(); i++){
- SSTRING *s = lst.getitem(i);
- if (s->is_empty()){
- lst.remove_del (s);
- i--;
- }
- }
- linuxconf_replace (IPALIAS,devname,lst);
- linuxconf_save();
- break;
- }
- }
- }
- }
-
- void alias_edit()
- {
- SSTRINGS lst;
- if (devlist_read(lst)!=-1){
- int sel = 0;
- while (1){
- DIALOG dia;
- int n = lst.getnb();
- lst.sort();
- for (int i=0; i<n; i++){
- dia.new_menuitem ("",lst.getitem(i)->get());
- }
- MENU_STATUS code = dia.editmenu (
- MSG_U(T_IPALIASES,"Edit IP aliases configurations")
- ,MSG_U(I_SYSTEMS,"Each network device may have several\n"
- "IP number. Alternate ones are called alias and are\n"
- "entered here.\n")
- ,help_aliases
- ,sel,0);
- if (code == MENU_OK){
- if (n > 0){
- SSTRING *s = lst.getitem(sel);
- alias_edit (s->get());
- }
- }else if (code == MENU_ESCAPE || code == MENU_QUIT){
- break;
- }
- }
- }
- }
-
-